package healthylife.top.sync;

import lombok.Data;

import java.time.LocalDateTime;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 懒加载，用于数据 缓冲,避免多次调用原方法
 *
 * @author maoxiaomeng
 * @since 2023/3/8 10:44
 */
@Data
public class Lazy<T> implements Supplier<T> {

    /**
     * 利用 value 属性缓存 supplier 计算后的值
     */
    private T value;

    private long expireTime;

    private long valueGetTime;

    private Supplier<T> supplier;

    private Lazy(Supplier<T> supplier) {
        this.supplier = supplier;
    }

    @Override
    public T get() {
        if (this.value == null) {
            T newValue = supplier.get();
            if (newValue == null) {
                throw new IllegalStateException("value not be null");
            }
            value = newValue;
            return value;
        }
        return value;
    }

    /**
     * 指定ttl来获取值
     * @param ttl 能接受的过期时间 5000ms, 自创建始,该数据有效期为5s
     * @return
     */
    public T get(long ttl) {
        if (this.value == null || System.currentTimeMillis() > expireTime) {
            T newValue = supplier.get();
            valueGetTime = System.currentTimeMillis();
            expireTime = valueGetTime + ttl;
            if (newValue == null) {
                throw new IllegalStateException("value not be null");
            }
            value = newValue;
            return value;
        }
        return value;
    }

    public static <T> Lazy<T> of(Supplier<T> supplier) {
        return new Lazy<>(supplier);
    }

    public <S> Lazy<S> map(Function<? super T, ? extends S> function) {
        return Lazy.of(() -> function.apply(get()));
    }

    public <S> Lazy<S> flatMap(Function<? super T, ? extends Lazy<S>> function) {
        return Lazy.of(() -> function.apply(get()).get());
    }

    public <S> Lazy<S> flatMap(Function<? super T, ? extends Lazy<S>> function, int depth) {
        return Lazy.of(() -> function.apply(get()).get());
    }

}
